#include <stdio.h>
#include <stdlib.h>

void *aligned_malloc(size_t required_bytes, size_t alignment) {
  int offset = alignment - 1 + sizeof(void *);
  void *p1 = (void *)malloc(required_bytes + offset);
  if (p1 == NULL)
    return NULL;
  void **p2 = (void **)(((size_t)p1 + offset) & ~(alignment - 1));
  p2[-1] = p1;
  return p2;
}

void aligned_free(void *p2) {
  void *p1 = ((void **)p2)[-1];
  free(p1);
}

void show(double *matrix, size_t size) {
  for (size_t i = 0; i < size; i += size / 4) {
    for (size_t j = 0; j < size; j += size / 4) {
      printf("%lf ", matrix[i * size + j]);
    }
    printf("\n");
  }
  printf("\n");
}

void init(double **A, double **B, double **C, size_t size) {
  *A = (double *)aligned_malloc(size * size * sizeof(double), 32);
  *B = (double *)aligned_malloc(size * size * sizeof(double), 32);
  *C = (double *)aligned_malloc(size * size * sizeof(double), 32);
  printf("%lx %lx %lx\n", (long)*A, (long)*B, (long)*C);
  for (size_t i = 0; i < size; i++) {
    for (size_t j = 0; j < size; j++) {
      (*A)[i + j * size] = i * 0.1 + j * 0.2;
      (*B)[i + j * size] = i * 0.3 + j * 0.1;
      (*C)[i + j * size] = 0;
    }
  }
  // show(*A, size);
  // show(*B, size);
}

void mfree(double *A, double *B, double *C) {
  aligned_free(A);
  aligned_free(B);
  aligned_free(C);
}